package com.fr.base.core.list;

import com.fr.base.FRContext;
import com.fr.base.core.util.SerializationUtils;
import com.fr.base.file.CacheManager;
import com.fr.util.Utils;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class FRCacheList extends AbstractList
  implements Serializable
{
  private static final long serialVersionUID = 1L;
  private static List prefix_list = new ArrayList();
  private File cacheDirectory;
  private int initCount;
  private String prefix;
  private int activePoolCount;
  private boolean cacheFirst;
  private ActiveFileInfo firstCacheInfo;
  private List cacheFileList;
  private IntList cacheIndexList;
  private ArrayList lastCachePool;
  private LinkedList cachedPoolIndexLL;
  private Map activeCachePoolMap;

  public FRCacheList(int paramInt, String paramString)
  {
    this(paramInt, 1, paramString, false);
  }

  public FRCacheList(int paramInt1, int paramInt2, String paramString)
  {
    this(paramInt1, paramInt2, paramString, false);
  }

  public FRCacheList(int paramInt1, int paramInt2, String paramString, boolean paramBoolean)
  {
    this.cacheDirectory = null;
    this.initCount = 800;
    this.prefix = "FRCL";
    this.activePoolCount = 1;
    this.cacheFirst = false;
    this.firstCacheInfo = null;
    this.cacheFileList = new ArrayList();
    this.cacheIndexList = new IntList();
    this.lastCachePool = new ArrayList();
    this.activeCachePoolMap = new HashMap();
    this.initCount = paramInt1;
    paramString = paramString.replaceAll("_", "");
    this.prefix = "FRCL" + paramString;
    String str = this.prefix;
    for (int i = 1; prefix_list.contains(str); ++i)
      str = this.prefix + i;
    this.prefix = str;
    prefix_list.add(this.prefix);
    this.cacheIndexList.add(0);
    this.activePoolCount = paramInt2;
    initCachePoolIndexLL();
    this.cacheFirst = paramBoolean;
  }

  private void initCachePoolIndexLL()
  {
    this.cachedPoolIndexLL = new LinkedList();
    for (int i = 0; i < this.activePoolCount; ++i)
      this.cachedPoolIndexLL.add(new ActiveFileInfo(this, -3, null));
  }

  public synchronized int size()
  {
    return (this.cacheIndexList.get(this.cacheIndexList.size() - 1) + this.lastCachePool.size());
  }

  public synchronized boolean add(Object paramObject)
  {
    if (this.lastCachePool.size() >= this.initCount)
      try
      {
        this.cacheIndexList.add(size());
        if ((this.cacheIndexList.size() == 2) && (this.cacheFirst))
        {
          this.firstCacheInfo = new ActiveFileInfo(this, 0, this.lastCachePool);
          this.lastCachePool = new ArrayList();
          this.cacheFileList.add(new Object());
        }
        else
        {
          File localFile = new File(getCacheDirectory(), getPrefix() + "_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 1000.0D));
          for (int i = 0; localFile.exists(); ++i)
            localFile = new File(getCacheDirectory(), getPrefix() + "_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 1000.0D) + i);
          SerializationUtils.serializable(this.lastCachePool, localFile);
          this.lastCachePool.clear();
          localFile.deleteOnExit();
          this.cacheFileList.add(localFile);
        }
      }
      catch (Exception localException)
      {
        FRContext.getLogger().log(Level.WARNING, localException.getMessage(), localException);
      }
    this.lastCachePool.add(paramObject);
    return true;
  }

  public synchronized Object set(int paramInt, Object paramObject)
  {
    rangeCheck(paramInt);
    try
    {
      int i = getCachePoolFileIndex(paramInt);
      if (i == -2)
        return this.lastCachePool.set(paramInt - this.cacheIndexList.get(this.cacheIndexList.size() - 1), paramObject);
      ActiveFileInfo localActiveFileInfo = getCachePoolFileByFileIndex(i);
      if (localActiveFileInfo != null)
      {
        Object localObject = localActiveFileInfo.getActiveCachedPool().set(paramInt - this.cacheIndexList.get(localActiveFileInfo.getFileIndex()), paramObject);
        localActiveFileInfo.setChanged(true);
        return localObject;
      }
    }
    catch (Exception localException)
    {
      FRContext.getLogger().log(Level.WARNING, localException.getMessage(), localException);
    }
    return null;
  }

  public synchronized void add(int paramInt, Object paramObject)
  {
    rangeCheck(paramInt);
    if (paramInt == size())
    {
      add(paramObject);
      return;
    }
    try
    {
      int i = getCachePoolFileIndex(paramInt);
      if (i == -2)
      {
        this.lastCachePool.add(paramInt - this.cacheIndexList.get(this.cacheIndexList.size() - 1), paramObject);
        return;
      }
      ActiveFileInfo localActiveFileInfo = getCachePoolFileByFileIndex(i);
      if (localActiveFileInfo != null)
      {
        localActiveFileInfo.getActiveCachedPool().add(paramInt - this.cacheIndexList.get(localActiveFileInfo.getFileIndex()), paramObject);
        for (int j = localActiveFileInfo.getFileIndex() + 1; j < this.cacheIndexList.size(); ++j)
          this.cacheIndexList.set(j, this.cacheIndexList.get(j) + 1);
        localActiveFileInfo.setChanged(true);
      }
    }
    catch (Exception localException)
    {
      FRContext.getLogger().log(Level.WARNING, localException.getMessage(), localException);
    }
  }

  public synchronized Object remove(int paramInt)
  {
    rangeCheck(paramInt);
    try
    {
      int i = getCachePoolFileIndex(paramInt);
      if (i == -2)
        return this.lastCachePool.remove(paramInt - this.cacheIndexList.get(this.cacheIndexList.size() - 1));
      ActiveFileInfo localActiveFileInfo = getCachePoolFileByFileIndex(i);
      if (localActiveFileInfo != null)
      {
        Object localObject = localActiveFileInfo.getActiveCachedPool().remove(paramInt - this.cacheIndexList.get(localActiveFileInfo.getFileIndex()));
        for (int j = localActiveFileInfo.getFileIndex() + 1; j < this.cacheIndexList.size(); ++j)
          this.cacheIndexList.set(j, this.cacheIndexList.get(j) - 1);
        localActiveFileInfo.setChanged(true);
        return localObject;
      }
    }
    catch (Exception localException)
    {
      FRContext.getLogger().log(Level.WARNING, localException.getMessage(), localException);
    }
    return null;
  }

  public synchronized Object get(int paramInt)
  {
    try
    {
      rangeCheck(paramInt);
      int i = getCachePoolFileIndex(paramInt);
      if (i == -2)
        return this.lastCachePool.get(paramInt - this.cacheIndexList.get(this.cacheIndexList.size() - 1));
      ActiveFileInfo localActiveFileInfo = getCachePoolFileByFileIndex(i);
      if (localActiveFileInfo != null)
        return localActiveFileInfo.getActiveCachedPool().get(paramInt - this.cacheIndexList.get(localActiveFileInfo.getFileIndex()));
    }
    catch (Exception localException)
    {
      FRContext.getLogger().log(Level.WARNING, localException.getMessage(), localException);
    }
    return null;
  }

  private void rangeCheck(int paramInt)
  {
    int i = size();
    if ((paramInt < 0) || (paramInt >= i))
      throw new IndexOutOfBoundsException("Index: " + paramInt + ",Size: " + i);
  }

  private int getCachePoolFileIndex(int paramInt)
  {
    if (paramInt >= this.cacheIndexList.get(this.cacheIndexList.size() - 1))
      return -2;
    if (paramInt < 0)
      return -1;
    int i = paramInt / this.initCount;
    if (this.cacheIndexList.get(i) <= paramInt)
    {
      j = i;
      while (true)
      {
        if (j >= this.cacheIndexList.size() - 1)
          break label139;
        if ((paramInt >= this.cacheIndexList.get(j)) && (paramInt < this.cacheIndexList.get(j + 1)))
          return j;
        ++j;
      }
    }
    for (int j = i - 1; j >= 0; --j)
      if ((paramInt >= this.cacheIndexList.get(j)) && (paramInt < this.cacheIndexList.get(j + 1)))
        return j;
    label139: return -1;
  }

  private ActiveFileInfo getCachePoolFileByFileIndex(int paramInt)
    throws IOException, ClassNotFoundException
  {
    if (paramInt < 0)
      return null;
    if ((paramInt == 0) && (this.firstCacheInfo != null))
      return this.firstCacheInfo;
    Integer localInteger = new Integer(paramInt);
    if (this.cachedPoolIndexLL.remove(localInteger))
    {
      this.cachedPoolIndexLL.add(localInteger);
      return ((ActiveFileInfo)this.activeCachePoolMap.get(localInteger));
    }
    ActiveFileInfo localActiveFileInfo1 = (ActiveFileInfo)this.activeCachePoolMap.remove(this.cachedPoolIndexLL.removeFirst());
    ChangeActiveCachedFile(localActiveFileInfo1);
    ArrayList localArrayList = getActiveFileFromDisk(paramInt);
    ActiveFileInfo localActiveFileInfo2 = new ActiveFileInfo(this, paramInt, localArrayList);
    this.cachedPoolIndexLL.add(localInteger);
    this.activeCachePoolMap.put(localInteger, localActiveFileInfo2);
    return localActiveFileInfo2;
  }

  private ArrayList getActiveFileFromDisk(int paramInt)
    throws IOException, ClassNotFoundException
  {
    File localFile = (File)this.cacheFileList.get(paramInt);
    return ((ArrayList)SerializationUtils.deserializable(localFile));
  }

  private synchronized void ChangeActiveCachedFile(ActiveFileInfo paramActiveFileInfo)
    throws IOException
  {
    if (paramActiveFileInfo == null)
      return;
    if (!(paramActiveFileInfo.isChanged()))
      return;
    File localFile = (File)this.cacheFileList.get(paramActiveFileInfo.getFileIndex());
    SerializationUtils.serializable(paramActiveFileInfo.getActiveCachedPool(), localFile);
  }

  public synchronized void clear()
  {
    this.lastCachePool.clear();
    this.cacheFileList.clear();
    this.cacheIndexList.clear();
    this.cacheIndexList.add(0);
    initCachePoolIndexLL();
    this.activeCachePoolMap.clear();
    if (this.firstCacheInfo != null)
    {
      ActiveFileInfo.access$000(this.firstCacheInfo).clear();
      this.firstCacheInfo = null;
    }
    if (this.cacheDirectory != null)
    {
      Utils.deleteFile(this.cacheDirectory);
      this.cacheDirectory = null;
    }
  }

  public String getPrefix()
  {
    return this.prefix;
  }

  public void setPrefix(String paramString)
  {
    this.prefix = paramString;
  }

  private File getCacheDirectory()
  {
    if (this.cacheDirectory == null)
    {
      this.cacheDirectory = new File(FRContext.getCacheManager().getCacheDirectory(), "DATA_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 1000.0D));
      for (int i = 0; this.cacheDirectory.exists(); ++i)
        this.cacheDirectory = new File(FRContext.getCacheManager().getCacheDirectory(), "DATA_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 1000.0D) + i);
      Utils.mkdirs(this.cacheDirectory);
      this.cacheDirectory.deleteOnExit();
    }
    return this.cacheDirectory;
  }

  public String toString()
  {
    return "FRCacheList" + hashCode();
  }

  protected void finalize()
    throws Throwable
  {
    finalize();
    if (this.cacheDirectory != null)
    {
      Utils.deleteFile(this.cacheDirectory);
      this.cacheDirectory = null;
    }
  }

  private class ActiveFileInfo
  {
    private int fileIndex;
    private ArrayList activeCachedPool;
    private boolean isChanged;
    private final FRCacheList this$0;

    public ActiveFileInfo(, int paramInt, ArrayList paramArrayList)
    {
      this.this$0 = paramFRCacheList;
      this.fileIndex = paramInt;
      this.activeCachedPool = paramArrayList;
      this.isChanged = false;
    }

    public int getFileIndex()
    {
      return this.fileIndex;
    }

    public ArrayList getActiveCachedPool()
    {
      return this.activeCachedPool;
    }

    public boolean isChanged()
    {
      return this.isChanged;
    }

    public void setChanged()
    {
      this.isChanged = paramBoolean;
    }

    static ArrayList access$000(ActiveFileInfo paramActiveFileInfo)
    {
      return paramActiveFileInfo.activeCachedPool;
    }
  }
}